package com.up.tools.exception;


import com.up.tools.annotation.EnableAutoTryCatch;
import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInterceptor;

import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.Pointcut;
import org.springframework.aop.PointcutAdvisor;
import org.springframework.aop.support.StaticMethodMatcherPointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

/**
 * @author: baiMl
 * @title: CommonTryCatchAdvisor
 * @projectName: 海联技术中台V2.0
 * @depart 软件事业部
 * @description:
 * @date: 2022/5/19 16:05
 */
public class CommonTryCatchAdvisor implements PointcutAdvisor {
    private final Logger log = LoggerFactory.getLogger(CommonTryCatchAdvisor.class);

    @Override
    @NonNull
    public Pointcut getPointcut() {
        return new StaticMethodMatcherPointcut() {
            @Override
            public boolean matches(@NonNull Method method, @NonNull Class<?> aClass) {
                return aClass.isAnnotationPresent(EnableAutoTryCatch.class) || method.isAnnotationPresent(EnableAutoTryCatch.class);
            }
        };
    }

    @Override
    @NonNull
    public Advice getAdvice() {
        return (MethodInterceptor) methodInvocation -> {
            try {
                Method method = methodInvocation.getMethod();
                Object[] arguments = methodInvocation.getArguments();
                Object aThis = methodInvocation.getThis();
                Parameter[] parameters = method.getParameters();
                if (log.isDebugEnabled()) {
                    log.debug("调用方法名称：{}", method.getName());
                    log.debug("调用方法的类：{}", aThis.getClass().getName());
                    for (int i = 0; i < parameters.length; i++) {
                        String name = parameters[i].getName();
                        log.debug("调用方法，第[{}]个参数名称为[{}],参数值为[{}]", i, name, arguments[i]);
                    }
                }
                Object proceed = methodInvocation.proceed();
                if (log.isDebugEnabled()) {
                    log.debug("方法[{}]调用完成，调用返回值:{}", method.getName(), proceed);
                }
                return proceed;
            } catch (Exception exception) {
                log.error("方法调用出现异常，异常信息:{}", exception.getMessage());
                exception.printStackTrace();
                String message = exception.getMessage();
                if(StringUtils.isEmpty(message)){
                    message = "调用出现异常，异常栈无对应的异常信息，请查看后端日志详细分析错误原因";
                }
                return message;
            }
        };
    }

    @Override
    public boolean isPerInstance() {
        return false;
    }
}